<?php
declare (strict_types=1);

namespace app\common\service;

use app\admin\logic\system\Config as SystemConfig;
use app\common\exception\LogicException;
use app\common\logic\{Attach, Payment, Template};
use app\common\logic\advert\AdvertLink;
use app\common\logic\navi\{NaviBottom, NaviTop};
use app\common\model\discovery\Discovery;
use app\content\logic\content\Agreement;
use app\user\event\subscribes\user\Account as UserSubscribe;
use app\user\logic\user\Account;
use app\user\model\user\ThirdLogin;
use eduline\login\exception\GatewayError;
use eduline\login\Login;
use think\db\exception\{DataNotFoundException, DbException, ModelNotFoundException};
use think\Exception;
use think\facade\{Config as ThinkConfig, Event, Request};
use think\Response;

/**
 * 配置接口类
 */
class Config extends BaseService
{
    /**
     * 是否独立域名
     * Author: 亓官雨树 <lucky.max@foxmail.com>
     * Date: 23/03/23
     *
     * @return Response
     */
    public function isSdn(): Response
    {
        $sdn = ['mhm_id' => request()->mhm_id, 'mhm_sdn' => request()->mhm_sdn];

        return static::parseToData($sdn, 1, '获取成功');
    }

    /**
     * 初始化
     * Author: 亓官雨树 <lucky.max@foxmail.com>
     * Date: 21/09/09
     *
     * @return Response
     */
    public function initApp(): Response
    {
        // sdk_appid
        $live_conf = SystemConfig::get('course.live.config.tic', ['key' => '', 'sdk_appid' => '', request()->mhm_id]);
        $sdk_appid = $live_conf['sdk_appid'];
        // 主题色
        $theme_conf  = SystemConfig::get('site.theme.color', ['color' => ''], request()->mhm_id);
        $theme_color = $theme_conf['color'];
        // IOS余额展示配置
        $ios_bconf = SystemConfig::get('recharge.config.ios', ['title' => '$'], request()->mhm_id);
        // 站点信息
        $site_info = SystemConfig::get('site.info', [], request()->mhm_id);
        // pc_logo
        if ($site_info['pc_logo'] ?? false) {
            $site_info['pc_logo_url'] = app(Attach::class)->where('id', $site_info['pc_logo'])->findOrEmpty()->getAttr('fileurl');
        }
        // h5_logo
        if ($site_info['h5_logo'] ?? false) {
            $site_info['h5_logo_url'] = app(Attach::class)->where('id', $site_info['h5_logo'])->findOrEmpty()->getAttr('fileurl');
        }
        // pc_logo
        if ($site_info['ico'] ?? false) {
            $site_info['ico_url'] = app(Attach::class)->where('id', $site_info['ico'])->findOrEmpty()->getAttr('fileurl');
        }
        // official_qr
        if ($site_info['official_qr'] ?? false) {
            $site_info['official_qr_url'] = app(Attach::class)->where('id', $site_info['official_qr'])->findOrEmpty()->getAttr('fileurl');
        }

        $school_app = SystemConfig::get('system.school.app', ['school_app' => 0], request()->mhm_id);

        $payway = app(Payment::class)->payway();
        $apps   = ThinkConfig::get('eduline.appinfo.open_app', []);
        $school = in_array('school', $apps);
        $mhm    = ThinkConfig::get('eduline.appinfo.mhm', true);
        $init   = [
            'mhm_id'        => request()->mhm_id,
            'mhm_sdn'       => request()->mhm_sdn,
            'sdk_appid'     => $sdk_appid,
            'theme_color'   => $theme_color,
            'ios_bconf'     => $ios_bconf,
            'login_config'  => $this->login(false),
            'payway_config' => $payway,
            'school_app'    => $school_app['school_app'],
            'saas'          => $mhm && $school,
            'site_info'     => $site_info,
            'register_agre' => Request::domain() . '/content/agreement/userRegister/content/' . request()->mhm_id,
            'content_conf'  => app(Agreement::class)->where('mhm_id', request()->mhm_id)->column('key,title')
        ];
        // 触发自动登录事件
        Event::subscribe(UserSubscribe::class);
        Event::trigger('UserAutoLogin', request()->user);

        return static::parseToData($init, 1, '获取成功');
    }

    /**
     * 全局开关
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date 2021-09-09
     */
    public function switch(): Response
    {
        $data   = [
            'system.school.app'          => 'school_app',
            'course.config.comment_note' => ['comment', 'note', 'exam', 'courseware'],
            'system.category'            => ['key' => 'use_public', 'title' => 'category_public'],
        ];
        $config = [];
        foreach ($data as $k => $v) {
            $conf = SystemConfig::get($k, [], request()->mhm_id);
            if (is_array($v)) {
                if (array_key_exists('key', $v) && array_key_exists('title', $v)) {
                    $config[$v['title']] = $conf[$v['key']] ?? 0;
                } else {
                    foreach ($v as $title) {
                        $config[$title] = $conf[$title] ?? 0;
                    }
                }
            } else {
                $config[$v] = $conf[$v] ?? 0;
            }
        }
        // 人脸识别
        $faceConfig           = SystemConfig::get('face.config', [], request()->mhm_id);
        $scene                = $faceConfig['scene'] ?? [];
        $config['face_scene'] = $scene;

        return static::parseToData($config, 1, '获取成功');
    }

    // 登录配置
    public function login($service = true)
    {
        $_conf = [
            'phone'  => 0, // 一键登录
            'verify' => 0, // 验证码登录
            'user'   => 0, // 账号登录
            'device' => 0, // 设备登录
        ];

        $login = SystemConfig::get('system.login', ['type' => []], request()->mhm_id);

        foreach ($_conf as $k => &$v) {
            if (in_array($k, $login['type'])) {
                $v = 1;
                if ($k == 'phone') {
                    $oneclick            = SystemConfig::get('system.login.oneclick', ['businessId' => ''], request()->mhm_id);
                    $_conf['businessId'] = $oneclick['businessId'];
                }
            }
        }
        unset($v);

        $_conf['register_agre'] = Request::domain() . '/content/agreement/userRegister/content/' . request()->mhm_id;

        return $service ? static::parseToData($_conf, 1, '获取成功') : $_conf;
    }

    public function typeset(): Response
    {
        $default            = ['line_display_number' => 1];
        $profile            = SystemConfig::get('site.personal.display', $default, request()->mhm_id);
        $course             = SystemConfig::get('site.course.display', $default, request()->mhm_id);
        $typeset['profile'] = $profile['line_display_number'];
        $typeset['course']  = $course['line_display_number'];

        return static::parseToData($typeset, 1, '获取成功');
    }

    // 发现页

    /**
     * @throws ModelNotFoundException
     * @throws DbException
     * @throws DataNotFoundException
     */
    public function discovery(): Response
    {
        $map       = [];
        $schoolApp = SystemConfig::get('system.school.app', ['school_app' => 0]);
        if ($schoolApp['school_app'] && request()->mhm_id != 1) {
            $map[] = ['key', '<>', 'school'];
        }
        // 获取应用配置
        $items = app(Discovery::class)->where($map)->with(['discoveryData', 'iconUrl'])->field('title,key,icon')->order(['sort' => 'asc', 'update_time' => 'desc'])->select();

        foreach ($items as $k => &$item) {
            $discoveryData = $item->discoveryData;
            if ($discoveryData) {
                if (!$discoveryData->status) {
                    unset($items[$k]);
                    continue;
                }
                $item['icon_url'] = $discoveryData->icon ? $discoveryData->icon_url : '';
                $item['title']    = $discoveryData->title ?: $item['title'];
            }
        }
        unset($item);
        $items->hidden(['discoveryData', 'icon']);

        return static::parseToData(array_values($items->toArray()), 1, '获取成功');
    }

    public function naviTopTree(): Response
    {
        $tempType = request()->is_pc ? 'pc_home' : 'mobile_home';
        $temp     = app(Template::class)->where('template_type', $tempType)->findOrEmpty();
        if (!$temp->isEmpty() && count($temp->template_data)) {
            $data = [];
            foreach ($temp->template_data as $item) {
                if (in_array($item['component'], ['navigation', 'topNav'])) {
                    $data = $item['setStyle']['form']['source_list'] ?? [];
                }
            }
            if (!count($data)) {
                // 获取应用配置
                $data = app(NaviTop::class)->getTree();
            }
        } else {
            // 获取应用配置
            $data = app(NaviTop::class)->getTree();
        }

        return static::parseToData($data, 1, '获取成功');
    }

    public function naviBottomTree(): Response
    {
        // 获取应用配置
        $data = app(NaviBottom::class)->getTree();

        return static::parseToData($data, 1, '获取成功');
    }

    public function getBanner(): Response
    {
        $banner = [];
        $type   = Request::has('type', 'get', true) ? Request::get('type/s') : '';
        $mhm_id = Request::has('mhm_id', 'get', true) ? Request::get('mhm_id/d') : 0;
        $is_pc  = request()->is_pc;

        if (!$mhm_id) throw new LogicException('参数错误');

        if ($type) {
            switch ($type) {
                case 'home':
                    $key = $is_pc ? 'pc.index' : 'index';
                    break;

                case 'school':
                    $key = $is_pc ? 'pc.school.index' : '';
                    break;

                case 'advert':
                    $key = $is_pc ? 'pc.advert' : 'advert';
                    break;

                case 'topic':
                    $key = $is_pc ? 'pc.topic.index' : 'topic.index';
                    break;

                default:
                    throw new LogicException('参数错误');
            }

            $banner = app(AdvertLink::class)->getLinkByKeyAndMhmId($key, $mhm_id);
        }

        return static::parseToData($banner, 1, '获取成功');
    }

    public function thirdlogin(): Response
    {
        // 端别
        $deviceType = request()->device_type;
        // 回调地址
        $redirectUri = input('get.redirect_uri/s') ?? '';
        // PC、h5检查回调
        if (in_array($deviceType, ['pc', 'h5']) && !$redirectUri) throw new LogicException('请配置回调页面地址');
        // 开启的三方登录配置
        $loginConf  = SystemConfig::get('system.package.login', [], request()->mhm_id);
        $thirdlogin = [];

        foreach ($loginConf as $login) {
            // 三方登录配置
            $loginConfThird = SystemConfig::get('system.package.login.' . $login, ['open_device' => []], request()->mhm_id);
            // 开放的登录端别
            $openDevice = $loginConfThird['open_device'];
            // 当前端别未开启返回
            if (!in_array($deviceType, $openDevice)) continue;
            // 当前端别开启，处理
            if (in_array($deviceType, ['pc', 'h5'])) {
                if ($deviceType == 'h5' && $login == 'weixin') {
                    // $appid              = $loginConfThird['app_key']??'';
                    $official = SystemConfig::get('system.config.official', [], request()->mhm_id);
                    $appid    = $official['appid'] ?? '';
                    // $uri = Des::jiami(urldecode($redirectUri));
                    // $thirdlogin[$login] = 'http://seition.com/weauth?ruk='.$uri;
                    $thirdlogin[$login] = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=$appid&redirect_uri=$redirectUri&response_type=code&scope=snsapi_userinfo&state=weixin#wechat_redirect";
                } else {
                    $thirdlogin[$login] = $this->getCodeUrl($login, $redirectUri);
                }
            } else {
                $thirdlogin[] = $login;
            }
        }

        return static::parseToData($thirdlogin, 1, '获取成功');
    }

    private function getCodeUrl($type, $redirectUri)
    {
        $config    = [];
        $login     = Login::$type(['callback' => $redirectUri]);
        $authorize = array_merge(['state' => $type], $config);
        $login->authorize($authorize);

        return $login->getRequestCodeURL();
    }

    // 获取用户信息/openid
    public function thirdloginCheck(): Response
    {
        $code = Request::get('code/s');
        $type = Request::get('type/s');
        $uri  = Request::get('redirect_uri/s');
        if (!in_array($type, ['weixin', 'qq', 'sina'])) throw new LogicException('请求参数错误');

        $login = Login::$type(['callback' => $uri]);
        $token = $login->getAccessToken($code);
        $oauth = $token['unionid'] ?? $token['openid'];
        // $openid = $token['openid'];

        $user_id = app(ThirdLogin::class)->where('oauth', $oauth)->where('type', $type)->value('user_id');

        if ($user_id) {
            // 用户信息
            $user = $this->userData($user_id);

            return static::parseToData(['has_bind' => 1, 'user' => $user], 1, '获取成功');
        } else {
            // 返回oauth
            return static::parseToData(['has_bind' => 0, 'oauth' => $oauth], 1, '获取成功');
        }
    }

    // H5微信登录绑定
    public function thirdloginH5bind(): Response
    {
        $code  = Request::get('code/s');
        $phone = Request::get('phone/d');
        if (!$code) throw new LogicException('参数错误');

        $authorize = [];
        $official  = SystemConfig::get('system.config.official', [], request()->mhm_id);
        $appid     = $official['appid'] ?? '';
        $appid && $authorize = $official;

        $login = Login::weixin();
        $login->authorize($authorize);
        $token  = $login->getAccesstoken($code);
        $oauth  = $token['unionid'] ?? $token['openid'];
        $openid = $token['openid'];

        $user_id = app(ThirdLogin::class)->where('oauth', $oauth)->where('type', 'weixin')->value('user_id');
        // 有user_id，已绑定，直接获取用户信息登录
        if ($user_id) {
            // 用户信息
            $user = $this->userData($user_id);

            return static::parseToData(['has_bind' => 2, 'user' => $user, 'oauth' => $oauth, 'openid' => $openid], 1, '绑定成功');
        } else {
            // 无user_id, 未绑定，有phone,去绑定，无phone,表示直接微信登录，去绑定
            if ($phone) {
                // 用户
                $user_id = app(Account::class)->wherePhone($phone)->where('mhm_id', request()->mhm_id)->value('id');
                if (!$user_id) throw new LogicException('未查询到用户信息');
                // 绑定
                $re = ThirdLogin::create([
                    'oauth'   => $oauth,
                    'type'    => 'weixin',
                    'user_id' => $user_id
                ]);
                if ($re->isEmpty()) throw new LogicException('绑定失败');

                // 用户信息
                return static::parseToData(['has_bind' => 1, 'oauth' => $oauth, 'openid' => $openid], 1, '绑定成功');
            } else {
                return static::parseToData(['has_bind' => 0, 'oauth' => $oauth, 'openid' => $openid], 1, '获取成功');
            }
        }
    }

    // 微信获取openid
    public function thirdloginOpenid(): Response
    {
        $code = Request::get('code/s');
        if (!$code) throw new LogicException('参数错误');

        $authorize = [];
        // $official  = SystemConfig::get('system.config.official', [], request()->mhm_id);
        // $appid     = $official['appid'] ?? '';
        // $appid && $authorize = $official;
        try {
            $login = Login::weixin();
            $login->authorize($authorize);
            $token  = $login->getAccesstoken($code);
            $openid = $token['openid'] ?? '';

            // $desOpenid = Des::jiami($openid);
            return static::parseToData(['openid' => $openid], 1, '获取成功');
        } catch (GatewayError|Exception $e) {
            throw new LogicException($e->getMessage());
        }
    }

    // 用户信息
    public function userData($user_id)
    {
        $user = app(Account::class)->findOrEmpty($user_id);

        // 账号状态是否正常
        if ($user->status === 0) throw new LogicException('账号已被禁止登录');
        //
        $user->need_set_password = 0;
        // 如果没有设置密码,提示设置密码
        if ($user->password == '') $user->need_set_password = 1;
        //
        $user->ticket = app(Account::class)->getUserLoginTicket($user->id, $user->last_login_time, $user->create_time);
        // 登录成功
        Event::subscribe(UserSubscribe::class);
        Event::trigger('UserLogin', $user);

        return $user;
    }
}
